package com.xh.bussiness.exam.controller;

import com.alibaba.druid.support.json.JSONUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xh.bussiness.exam.bean.dto.StudentErrorTotalStatDto;
import com.xh.bussiness.exam.bean.dto.StudentReportForAppletDto;
import com.xh.bussiness.exam.bean.request.QueryStuErrQuesCollesRequest;
import com.xh.bussiness.exam.bean.request.StudentErrorTotalStatRequest;
import com.xh.bussiness.exam.model.PaperQuestionTestDetail;
import com.xh.bussiness.exam.model.UserErrorQuestion;
import com.xh.bussiness.exam.model.UserErrorQuestionCorrectLog;
import com.xh.bussiness.exam.service.IPaperTestService;
import com.xh.bussiness.exam.service.IUserErrorQuestionCorrectLogService;
import com.xh.bussiness.exam.service.IUserErrorQuestionService;
import com.xh.bussiness.tiku.bean.dto.QuestionDto;
import com.xh.bussiness.tiku.constant.PaperConstant;
import com.xh.bussiness.tiku.service.IQuestionKnowledgeService;
import com.xh.bussiness.tiku.service.IQuestionService;
import com.xh.core.bean.AjaxResult;
import com.xh.core.constant.AjaxResultConstant;
import com.xh.core.util.DateUtils;
import com.xh.core.util.MathUtils;
import com.xh.core.util.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.temporal.WeekFields;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * <p>
 * 学生统计报告
 * </p>
 *
 * @author Pitt zhang
 * @since 2019/10/31
 */
@Api(tags = "测评-学生统计报告")
@RestController
@RequestMapping("/exam/student/report")
public class StudentReportController {

    Logger log = LoggerFactory.getLogger(StudentReportController.class);

    @Autowired
    private IUserErrorQuestionCorrectLogService userErrorQuestionCorrectLogService;
    @Autowired
    private IQuestionKnowledgeService questionKnowledgeService;
    @Autowired
    private IPaperTestService paperTestService;
    @Autowired
    private IQuestionService questionService;
    @Autowired
    private IUserErrorQuestionService userErrorQuestionService;

    @ApiOperation("学生周错题报告")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "studentId", value = "学生ID", dataType = "String", required = true),
            @ApiImplicitParam(name = "year", value = "年份", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "month", value = "月份", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "day", value = "日", dataType = "Integer", required = true),
    })
    @RequestMapping("/queryStudentWeekErrorQuestionReport")
    public AjaxResult queryStudentWeekErrorQuestionReport(String studentId, Integer year, Integer month, Integer day) {
        if (StringUtils.isEmpty(studentId) || year == null || month == null || day == null) {
            return new AjaxResult(AjaxResultConstant.Result.ERROR, "参数错误");
        }
        log.debug("queryStudentWeekErrorQuestionReport params:" + studentId + "," + year + "," + month + "," + day);
        //新增错题数
        Integer newErrorQuestionCount = 0;
        //消灭错题数
        Long dieErrorQuestionCount = 0L;
        //新增薄弱知识点
        Integer newKnowledgePoint = 0;
        //练习题目数
        Integer practiceCount = 0;
        //练习正确率
        Double practiceRightRate = 0.0;
        //综合评价
        String evaluate = "初出茅庐";
        //获取所选周的开始时间和结束时间
        String startDayOfWeek = getStartDayAndEndDayOfWeekNo(year, month, day).get(0);
        String endDayOfWeek = getStartDayAndEndDayOfWeekNo(year, month, day).get(1);
        //根据时间查询学生错题日志
        QueryWrapper<UserErrorQuestionCorrectLog> logQueryWrapper = new QueryWrapper<>();
        logQueryWrapper.eq("student_id", studentId);
        logQueryWrapper.ge("create_time", startDayOfWeek);
        logQueryWrapper.le("create_time", endDayOfWeek);
        List<UserErrorQuestionCorrectLog> userErrorQuestionCorrectLogs = userErrorQuestionCorrectLogService.selectList(logQueryWrapper, UserErrorQuestionCorrectLog.class);
        if (!CollectionUtils.isEmpty(userErrorQuestionCorrectLogs)) {
            //新增错题数
            List<String> newErrorQuestions = userErrorQuestionCorrectLogs.stream().filter(item -> item.getStatus().equals(0)).map(item -> item.getQuestionId()).distinct().collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(newErrorQuestions)) {
                newErrorQuestionCount = newErrorQuestions.size();
                //新增薄弱知识点
                List<Integer> knowledgeCount = questionKnowledgeService.queryQuestionKnowledgeCount(newErrorQuestions);
                if (!CollectionUtils.isEmpty(knowledgeCount)) {
                    newKnowledgePoint = knowledgeCount.stream().collect(Collectors.summingInt(item -> item));
                }
            }
            //消灭错题数
            dieErrorQuestionCount = userErrorQuestionCorrectLogs.stream().filter(item -> item.getStatus().equals(1)).map(item -> item.getQuestionId()).distinct().count();
        }
        //查询学生作答记录
        List<PaperQuestionTestDetail> paperQuestionTestDetails =
                paperTestService.queryStudentTestDetail(studentId, startDayOfWeek, endDayOfWeek, PaperConstant.TYPE.ERROR_QUESTION_TEST);
        if (!CollectionUtils.isEmpty(paperQuestionTestDetails)) {
            //练习题目数
            practiceCount = paperQuestionTestDetails.size();
            Long rightCount = paperQuestionTestDetails.stream().filter(item -> item.getAnswerResult().equals(1)).count();
            practiceRightRate = MathUtils.getNumberRate(MathUtils.divTwoNumberRoundHalfUp(practiceCount, rightCount.intValue(), MathUtils.DEFAULT_SCALE), MathUtils.DEFAULT_SCALE);
        }
        /*消灭错题数0-20：初出茅庐
        消灭错题数21-40：小试牛刀
        消灭错题数41-60：登堂入室（改）
        消灭错题数61-80：炉火纯青
        81-100：游刃有余
        101-200：登峰造极
        201以上：返璞归真*/
        if (newErrorQuestionCount >= 21 || newErrorQuestionCount <= 40) {
            evaluate = "小试牛刀";
        } else if (newErrorQuestionCount >= 41 || newErrorQuestionCount <= 60) {
            evaluate = "登堂入室";
        } else if (newErrorQuestionCount >= 61 || newErrorQuestionCount <= 80) {
            evaluate = "炉火纯青";
        } else if (newErrorQuestionCount >= 81 || newErrorQuestionCount <= 100) {
            evaluate = "游刃有余";
        } else if (newErrorQuestionCount >= 101 || newErrorQuestionCount <= 200) {
            evaluate = "登峰造极";
        } else if (newErrorQuestionCount >= 201) {
            evaluate = "返璞归真";
        }

        Map<String, Object> retMap = new HashMap<>();
        retMap.put("newErrorQuestionCount", newErrorQuestionCount);
        retMap.put(" dieErrorQuestionCount", dieErrorQuestionCount);
        retMap.put(" newKnowledgePoint", newKnowledgePoint);
        retMap.put(" practiceCount", practiceCount);
        retMap.put(" practiceRightRate", practiceRightRate);
        retMap.put(" evaluate", evaluate);
        return new AjaxResult(AjaxResultConstant.Result.SUCCESS, retMap);
    }

    @ApiOperation("学生周错题列表")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "studentId", value = "学生ID", dataType = "String", required = true),
            @ApiImplicitParam(name = "year", value = "年份", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "month", value = "月份", dataType = "Integer", required = true),
            @ApiImplicitParam(name = "day", value = "日", dataType = "Integer", required = true),
    })
    @RequestMapping("/queryStudentErrorQuestionsOfWeek")
    public AjaxResult queryStudentErrorQuestionsOfWeek(String studentId, Integer year, Integer month, Integer day) {
        if (StringUtils.isEmpty(studentId) || year == null || month == null || day == null) {
            return new AjaxResult(AjaxResultConstant.Result.ERROR, "参数错误");
        }
        log.debug("queryStudentErrorQuestionsOfWeek params:" + studentId + "," + year + "," + month + "," + day);
        //获取所选周的开始时间和结束时间
        String startDayOfWeek = getStartDayAndEndDayOfWeekNo(year, month, day).get(0);
        String endDayOfWeek = getStartDayAndEndDayOfWeekNo(year, month, day).get(1);
        //根据时间查询学生错题日志
        QueryWrapper<UserErrorQuestionCorrectLog> logQueryWrapper = new QueryWrapper<>();
        logQueryWrapper.eq("student_id", studentId);
        logQueryWrapper.ge("create_time", startDayOfWeek);
        logQueryWrapper.le("create_time", endDayOfWeek);
        List<UserErrorQuestionCorrectLog> userErrorQuestionCorrectLogs = userErrorQuestionCorrectLogService.selectList(logQueryWrapper, UserErrorQuestionCorrectLog.class);

        List<Map<String, Object>> questionList = new ArrayList<>();
        if (!CollectionUtils.isEmpty(userErrorQuestionCorrectLogs)) {
            List<String> newErrorQuestionIds = userErrorQuestionCorrectLogs.stream().filter(item -> item.getStatus().equals(0)).map(item -> item.getQuestionId()).distinct().collect(Collectors.toList());
            for (String questionId : newErrorQuestionIds) {
                Map<String, Object> questionMap = new HashMap<>();
                QuestionDto question = questionService.getQuestion(questionId, null, true,false,false,false,false);
                //学生错题详情
                UserErrorQuestion userErrorQuestion = userErrorQuestionService.queryUserErrorQuestionByStuIdAndQuesId(studentId, questionId);
                questionMap.put("question", question);
                questionMap.put("isCorrect", userErrorQuestion.getStatus());
                questionList.add(questionMap);
            }
        }
        return new AjaxResult(AjaxResultConstant.Result.SUCCESS, questionList);
    }

    /**
     * 根据年月日获取周的开始结束时间
     *
     * @param year
     * @param month
     * @param day
     * @return
     */
    List<String> getStartDayAndEndDayOfWeekNo(Integer year, Integer month, Integer day) {
        //获取所选周的开始时间和结束时间
        LocalDate localDate1 = LocalDate.of(year, month, day);
        WeekFields weekFields = WeekFields.of(DayOfWeek.MONDAY, 4);
        int weekNo = localDate1.get(weekFields.weekOfWeekBasedYear());
        String startDayOfWeek = DateUtils.getStartDayOfWeekNo(year, weekNo);
        String endDayOfWeek = DateUtils.getEndDayOfWeekNo(year, weekNo);
        return Stream.of(startDayOfWeek, endDayOfWeek).collect(Collectors.toList());
    }

    /**
     * 学生错题汇总统计
     * @param request
     * @return
     */
    @ApiOperation("学生错题汇总统计")
    @RequestMapping("/queryStudentErrorTotalStat")
    public AjaxResult queryStudentErrorTotalStat(@RequestBody StudentErrorTotalStatRequest request){
        if(StringUtils.isEmpty(request.getStudentId())){
            return new AjaxResult(AjaxResultConstant.Result.ERROR, "学员ID不能为空");
        }
        if(StringUtils.isEmpty(request.getGradeRange())){
            return new AjaxResult(AjaxResultConstant.Result.ERROR, "学段不能为空");
        }
        if(StringUtils.isEmpty(request.getSubjectId())){
            return new AjaxResult(AjaxResultConstant.Result.ERROR, "学科不能为空");
        }
        StudentErrorTotalStatDto studentErrorTotalStatDto=null;
        studentErrorTotalStatDto=userErrorQuestionService.queryStudentErrorTotalStat(request);
        return new AjaxResult(AjaxResultConstant.Result.SUCCESS, null,studentErrorTotalStatDto);
    }


    @ApiOperation("小程序学生端统计报告")
    @ApiImplicitParam(name = "studentId", value = "学生ID",required = true)
    @RequestMapping("/queryStudentReportForApplet")
    public AjaxResult queryStudentReportForApplet(String studentId) {
        if (StringUtils.isEmpty(studentId)) {
            return new AjaxResult(AjaxResultConstant.Result.ERROR, "参数错误");
        }
        StudentReportForAppletDto dto =
                userErrorQuestionService.queryStudentReportForApplet(studentId);
        return new AjaxResult(AjaxResultConstant.Result.SUCCESS, dto);
    }

}
